package com.quotes.simulation;

import java.util.Map.Entry;

import org.apache.log4j.Logger;

import com.quotes.Configuration;
import com.quotes.Parameters;
import com.quotes.ParametersList;
import com.quotes.datamodell.DataRepository;
import com.quotes.datamodell.DataRow;
import com.quotes.datamodell.DataTable;
import com.quotes.datamodell.QuotesList;
import com.quotes.dates.TimePeriod;
import com.quotes.dates.TimeRange;
import com.quotes.dates.TimeRangeFactory;
import com.quotes.io.ExcelHelper;

public class MassSimulator
{
	private Logger logger = Logger.getLogger(getClass().toString());
	private ParametersList parametersList = new ParametersList();
	private int threadsRunning = 0;
	
	public MassSimulator() {
		parametersList.add(Configuration.getDefaultParameters());
		
		logger.debug("MassSimulator created!");
	}
	
	public void addToSimulation(String key, double[] values) {
		parametersList = parametersList.multiply(key, values);
	}
	
	public void addToSimulation(String key, boolean[] values) {
		parametersList = parametersList.multiply(key, values);
	}
	
	public void addToSimulation(String key, int[] values) {
		parametersList = parametersList.multiply(key, values);
	}
	
	public void addToSimulation(String key, String[] values) {
		parametersList = parametersList.multiply(key, values);
	}
	
	private DataTable createTable() {
		DataTable table = new DataTable();
		
		table.addColumn("result");
		table.addColumn("endValue");
		table.addColumn("daysAboveInitialCash");
		table.addColumn("daysBelowInitialCash");
		table.addColumn("buyCount");
		table.addColumn("sellCount");
		table.addColumn("lowOnCashCount");
		table.addColumn("wins");
		table.addColumn("losses");
		table.addColumn("fees");
		
		for (Entry<String, Object> entry : parametersList.get(0).entrySet()) {
			table.addColumn(entry.getKey());
		}
		
		return table;
	}
	
	private synchronized void addToTable(DataTable table, SimulationResult result, Parameters parameters) {
		DataRow row = new DataRow();
		
		row.addCell(result.getResult());
		row.addCell(result.getEndValue());
		row.addCell(result.getDaysAboveInitialCash());
		row.addCell(result.getDaysBelowInitialCash());
		row.addCell(result.getBuyCount());
		row.addCell(result.getSellCount());
		row.addCell(result.getLowOnCashCount());
		row.addCell(result.getWins());
		row.addCell(result.getLosses());
		row.addCell(result.getFees());
		
		for (Entry<String, Object> entry : parameters.entrySet()) {
			row.addCell(entry.getValue());
		}
		
		table.addRow(row);
	}
	
	public void simulate() {
		DataRepository repository = new DataRepository();
		repository.tryLoadFromExcel();
		final QuotesList quotesList = repository.getQuotesList();
		final TimeRange range = TimeRangeFactory.untilToday(TimePeriod.ONE_YEAR);
		final DataTable table = this.createTable();
		
		int count = 0;
		for (final Parameters parameters : parametersList.getParameters()) {
			Thread t = new Thread(new Runnable() {
				public void run() {
					threadsRunning++;
					AlgorithmicTrader trader = new AlgorithmicTrader(quotesList, range, parameters);
					SimulationResult result = trader.trade();
					addToTable(table, result, parameters);
					threadsRunning--;
				}
			});
			
			while (threadsRunning >= 5) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			t.start();
			count++;
			logger.debug("Simulation run " + count + " of " + parametersList.size() + " done!");
		}
		
		while (threadsRunning != 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		ExcelHelper excelHelper = new ExcelHelper();
		excelHelper.createNewWorkbook();
		excelHelper.createSheet("SimulationResults");
		excelHelper.writeToSheet("SimulationResults", table, 0, 0);
		excelHelper.saveExcelSheet("simulation.xls");
		
		logger.debug("Mass simulation done!");
	}
}
